#include "keyboard.h"
#include "delay_tick.h"
#include "led.h"

#define  KEY_DELAY  10  //中断去抖动间隔ms

volatile uint8_t  key;
// 行key_row 列key_col
uint8_t key_col, key_row = 0;


// A0-3外部中断 A9-12开漏输出
static void key_exti_mode(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    //使能A端口时钟，使用外部中断需要打开RCC_APB2Periph_AFIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    //Pin5、6、7、8为上拉输入
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; 		 //上拉输入
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStruct);	  //初始化GPIOA

    //用到GPIOA的Pin5、6、7、8、9、10、11、12，其中Pin9、10、11、12为开漏输出
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; 		 //开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStruct);	  //初始化GPIOA
    // Pin9、10、11、12输出低电平
    GPIO_ResetBits(GPIOA,GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12);

    //0-3中断线
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource2);
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3);

    EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3;
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_Init(&EXTI_InitStruct);
    

    //配置中断优先级
    NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);

    NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_Init(&NVIC_InitStruct);

    NVIC_InitStruct.NVIC_IRQChannel = EXTI2_IRQn;
    NVIC_Init(&NVIC_InitStruct);

    NVIC_InitStruct.NVIC_IRQChannel = EXTI3_IRQn;
    NVIC_Init(&NVIC_InitStruct);

    // 清除可能的挂起中断 
    EXTI_ClearITPendingBit(EXTI_Line0 | EXTI_Line1 | EXTI_Line2 | EXTI_Line3);
}

// 进入中断后切换GPIO状态
// A0-3开漏输出 A9-12上拉输入读取Pin值
static void key_change_mode(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    /* GPIO Ports Clock Enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);	 //使能A端口时钟
    // Pin5、6、7、8开漏输出
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; 		 //开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStruct);	  //初始化GPIOA
    // Pin9、10、11、12为上拉输入
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; 		 //开漏输出
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStruct);	  //初始化GPIOA

    // Pin5、6、7、8开漏输出低电平
    GPIO_ResetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
}

// 初始化矩阵键盘
void key_board_init(void)
{
    key_exti_mode();
    key = 0;
}

static uint8_t get_key_num(uint8_t num)//按键两引脚值相加（引脚只用到了前八个所以只有低 八位）
{
	switch(num)
	{
		case 0x11:key='0';break;
		case 0x12:key='1';break;
		case 0x14:key='2';break;
		case 0x18:key='3';break;
		case 0x21:key='4';break;
		case 0x22:key='5';break;
		case 0x24:key='6';break;
		case 0x28:key='7';break;
		case 0x41:key='8';break;
		case 0x42:key='9';break;
		case 0x44:key='A';break;
		case 0x48:key='B';break;
		case 0x81:key='C';break;
		case 0x82:key='D';break;
		case 0x84:key='E';break;		
		case 0x88:key='F';break;
	}
	return key;
}
//获取按键，返回0，没有键值，非0，获得键值
//该函数在中断中调用
uint8_t get_key(uint8_t key_row)
{
    uint8_t i = 0;
    uint8_t num = 0;
    key_col = 0;
	
	if(key_row)
	{
        // 切换IO模式
        key_change_mode();
        // 行key_row Pin0、1、2、3      列key_col Pin9、10、11、12
		for(i = 9; i <= 12; i++)
		{
            // 因为#define GPIO_Pin_9 (uint16_t)0x0200
			if(GPIO_ReadInputDataBit(GPIOA,(1<<i)) == Bit_RESET){
                key_col = 1 << (i - 9);
                num = key_col | key_row;
            }
		}
        key_exti_mode();
		return get_key_num(num);
	}
	else
	{
		return 0;
	}
}

// 行key_row Pin0、1、2、3      列key_col Pin9、10、11、12
// A0-3外部中断服务函数
void EXTI0_IRQHandler(void)
{
    //略微延时后，读取管脚状态，去除抖动
	delay_ms(KEY_DELAY);
    if(EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line0);
        key_row = 0x10;
    } else {
        return;
    }
    //执行中断灯亮一下
    LEDx(LED_D2,0);

    // 获取键值
    c = get_key(key_row);
}

void EXTI1_IRQHandler(void)
{
    //略微延时后，读取管脚状态，去除抖动
	delay_ms(KEY_DELAY);
    if(EXTI_GetITStatus(EXTI_Line1) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line1);
        key_row = 0x20;
    } else {
        return;
    }
    //执行中断灯亮一下
    LEDx(LED_D2,0);

    // 获取键值
    c = get_key(key_row);
}

void EXTI2_IRQHandler(void)
{
    //略微延时后，读取管脚状态，去除抖动
	delay_ms(KEY_DELAY);
    if(EXTI_GetITStatus(EXTI_Line2) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line2);
        key_row = 0x40;
    } else {
        return;
    }
    //执行中断灯亮一下
    LEDx(LED_D2,0);

    // 获取键值
    c = get_key(key_row);
}

void EXTI3_IRQHandler(void)
{
    //略微延时后，读取管脚状态，去除抖动
	delay_ms(KEY_DELAY);
    if(EXTI_GetITStatus(EXTI_Line3) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line3);
        key_row = 0x80;
    } else {
        return;
    }
    //执行中断灯亮一下
    LEDx(LED_D2,0);

    // 获取键值
    c = get_key(key_row);
}

// void EXTI9_5_IRQHandler(void)
// {
//     //略微延时后，读取管脚状态，去除抖动
// 	delay_ms(KEY_DELAY);

//     key_row = 0;
//     // 查询确定中断线
//     if(EXTI_GetITStatus(EXTI_Line5) != RESET)
//     {
//         key_row = 0x10;

//     } else if(EXTI_GetITStatus(EXTI_Line6) != RESET) {
//         key_row = 0x20;

//     } else if(EXTI_GetITStatus(EXTI_Line7) != RESET) {
//         key_row = 0x40;

//     } else if(EXTI_GetITStatus(EXTI_Line8) != RESET) {
//         key_row = 0x80;

//     } else {
//         return;
//     }

//     //执行中断灯亮一下
//     LEDx(LED_D2,0);

//     // 获取键值
//     c = get_key(key_row);
//     //有键按下
//     if (c != 0) {
//         //打印或者处理
//     }
//     EXTI_ClearITPendingBit(EXTI_Line5);
//     EXTI_ClearITPendingBit(EXTI_Line6);
//     EXTI_ClearITPendingBit(EXTI_Line7);
//     EXTI_ClearITPendingBit(EXTI_Line8);
// }
